package com.kty.methods.sjqm.method.qmdj;

import com.kty.methods.sjqm.dao.SjqmOther;
import com.kty.methods.utils.Utils;
import com.nlf.calendar.Lunar;
import lombok.Data;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

@Data
public class QiMen {

    private int year; // 年
    private int month; // 月
    private int day; // 日
    private int time; // 时
    private int minute; // 分
    private int second; // 秒
    private Lunar lunarDate; // 农历日期
    private String lunarDateStr; // 农历日期String格式
    private String solarDate; // 公历日期
    private String baZi; // 八字
    private String baZiWuXing; // 八字五行
    private String baZiNaYin; // 八字纳音

    private int sanYuan; // 1：上元    2：中元    3：下元
    private String yinYangDun; // 阴阳遁
    private int juNumber; // 局数
    private String jieQi; // 节气
    private String xunShou; // 旬首
    private String zhiFu; // 值符
    private String zhiShi; // 值使
    private String newZhiFu; // 新值符
    private String newZhiShi; // 新值使
    private String fuTou; // 符头
    private int zhiFuGongWeiNumber; // [值符]旋转前宫位数
    private int newZhiFuGongWeiNumber; // [值符]旋转后宫位数
    private int zhiShiGongWeiNumber; // [值使]旋转前宫位数
    private int newZhiShiGongWeiNumber; // [值符]旋转后宫位数

    private String[] jiuXingSanQiLiuYi; // [九星]旋转前宫位中的'三奇六仪'
    private String[] newJiuXing; // [九星]旋转后的信息

    private int zhengShou; // 0：正授   1：非正授
    private int chaoShen; // 0：超神   1：非超神

    private String[] sanQiLiuYi; // 三奇六仪
    private String[] liuJiaYinWei; // 六甲隐位

    private String[] renPan; // ★人盘
    private String[] diPan; // ★地盘
    private String[] tianPan; // ★天盘
    private String[] shenPan; // ★神盘

    private String spare; // 备用属性

//**********************************************************************************************************************

    private static final SjqmOther sjqmOther = new SjqmOther();

//======================================================================================================================

    /**
     * 获取并设置'公历日期'
     */
    public void solarDate() {

//        Solar solar = lunarDate.getSolar(); // 获取国历年月日

        int year = lunarDate.getSolar().getYear(); // 获取公历年
        int month = lunarDate.getSolar().getMonth(); // 获取公历月
        int day = lunarDate.getSolar().getDay(); // 获取公历日
        int hour = lunarDate.getSolar().getHour(); // 获取时
        int minute = lunarDate.getSolar().getMinute(); // 获取分
        int second = lunarDate.getSolar().getSecond(); // 获取秒

        setSolarDate(year + "年" + month + "月" + day + "日"  + hour + "时" + minute + "分" + second + "秒");

    }

    /**
     * 获取并设置'农历日期'String格式
     */
    public void lunarDateStr() {

        if(null != getSpare()){
            setLunarDateStr(getLunarDate() + "日(" + getSpare() + ")" + getLunarDate().getTimeZhi() + "时"); // 设置农历日期（附带早晚子时）
        }else {
            setLunarDateStr(getLunarDate() + "日" + getLunarDate().getTimeZhi() + "时"); // 设置农历日期
        }

    }

    /**
     * 获取并设置'八字'
     */
    public void baZi() {

        setBaZi(String.valueOf(lunarDate.getBaZi()));

    }

    /**
     * 获取并设置'八字五行'
     */
    public void baZiWuXing() {

        setBaZiWuXing(String.valueOf(lunarDate.getBaZiWuXing()));

    }

    /**
     * 获取并设置'八字纳音'
     */
    public void baZiNaYin() {

        setBaZiNaYin(String.valueOf(lunarDate.getBaZiNaYin()));

    }

//----------------------------------------------------------------------------------------------------------------------

    /**
     * 通用：判断 '日干支' 是否符合 上元符头 之一
     *
     * @param dayGanZhi 日干支
     * @return true：符合     false：不符合
     */
    private boolean isFlagUpFuTou(String dayGanZhi) {

        boolean isFlag = false; // 默认不符合

        // 判断日干支是否为上元符头
        for (String ft : sjqmOther.getUpFuTou()) {
            if (ft.equals(dayGanZhi)) {
                isFlag = true;
                break;
            }
        }
        return isFlag;

    }

    /**
     * 通用：判断 '日干支' 是否符合 八符头 之一
     *
     * @param dayGanZhi 日干支
     * @return true：符合     false：不符合
     */
    private boolean isFlagBaFuTou(String dayGanZhi) {

        boolean isFlag = false; // 默认不符合

        // 判断日干支是否为八符头
        for (String ft : sjqmOther.getBaFuTou()) {
            if (ft.equals(dayGanZhi)) {
                isFlag = true;
                break;
            }
        }
        return isFlag;

    }

    /**
     * 通用：判断 '日干支' 是否符合 十二符头 之一
     *
     * @param dayGanZhi 日干支
     * @return true：符合     false：不符合
     */
    private boolean isFlagFuTou(String dayGanZhi) {

        boolean isFlag = false; // 默认不符合

        // 判断日干支是否为十二符头
        for (String ft : sjqmOther.getFuTou()) {
            if (ft.equals(dayGanZhi)) {
                isFlag = true;
                break;
            }
        }
        return isFlag;

    }

    /**
     * 通用：根据（阴\阳）遁获取对应信息 &&调取diPanJiuGong()方法
     */
    private String[] getDiPan(String[] yangDun, String[] yinDun) {

        // 1、判断阴阳遁
        if ("阳遁".equals(getYinYangDun())) {
            // ①阳遁
            return diPanJiuGong(yangDun, getJuNumber());
            // ②阴遁
        } else return diPanJiuGong(yinDun, getJuNumber());

    }

    /**
     * 通用：返回【'地盘'九宫信息】
     * <p>
     * 阴\阳遁一局：初始阴/阳遁
     * 阴\阳遁二局：[前元素{8~9},后元素{0~8}]
     * 阴\阳遁三局：[前元素{7~9},后元素{0~7}]
     * 阴\阳遁四局：[前元素{6~9},后元素{0~6}]
     * 阴\阳遁五局：[前元素{5~9},后元素{0~5}]
     * 阴\阳遁六局：[前元素{4~9},后元素{0~4}]
     * 阴\阳遁七局：[前元素{3~9},后元素{0~3}]
     * 阴\阳遁八局：[前元素{2~9},后元素{0~2}]
     * 阴\阳遁九局：[前元素{1~9},后元素{0~1}]
     *
     * @param dun   阴\阳遁
     * @param juShu 局数
     * @return '地盘'九宫信息
     */
    protected String[] diPanJiuGong(String[] dun, int juShu) {

        // 1、元素截取
        String[] start = Arrays.copyOfRange(dun, (dun.length - juShu + 1), dun.length); // 前元素
        String[] end = Arrays.copyOfRange(dun, 0, (dun.length - juShu + 1)); // 后元素

        // 2、数组拼接
        // 2.1、获取数组长度
        int strLength = start.length; // 前元素长度
        int endLength = end.length; // 后元素长度
        // 2.2、数组扩容
        start = Arrays.copyOf(start, strLength + endLength);
        // 2.3、拷贝
        System.arraycopy(end, 0, start, strLength, endLength);

        // 3、返回九宫信息
        return start;

    }

    /**
     * 通用：返回【值符(九星之一)】落入地盘的宫位 <旋转前>
     *
     * @return 【值符(九星之一)】落入地盘的宫位 <旋转前>
     */
    protected int zhiFuGongWei() {

        String[] liuJiaYinWei = getLiuJiaYinWei(); // 获取[六甲隐位]

        int gongWei = 0; // 记录宫数
        // 判断'旬首'处于[六甲隐位]中的第几宫
        for (int i = 0; i < liuJiaYinWei.length; i++) {
            if (getXunShou().equals(liuJiaYinWei[i])) {
                gongWei = i;
                break;
            }
        }
        setZhiFuGongWeiNumber(gongWei + 1); // 设置[值符]旋转前宫位
        setZhiShiGongWeiNumber(gongWei + 1); // 设置[值使]旋转前宫位
        return (gongWei + 1);

    }

    /**
     * 设置【值符(九星之一)】落入地盘的宫位 <旋转后>
     */
    protected void newZhiFuGongWei() {

        String timeGan = lunarDate.getTimeGan(); // 获取时干
        String[] sanQiLiuYi = getSanQiLiuYi();// 获取地盘三奇六仪

        // 判断时干是否为'甲'
        if("甲".equals(timeGan)){
            String xunShou = getXunShou(); // 获取旬首
            String[] liuJiaYinWei = getLiuJiaYinWei(); // 获取六甲隐位
            // 判断'旬首'在'六甲隐位'中的第几宫
            for (int i = 0; i < liuJiaYinWei.length; i++) {
                if(xunShou.equals(liuJiaYinWei[i])){
                    setNewZhiFuGongWeiNumber(i + 1);
                    break;
                }
            }
        }

        // 判断时干出现在三奇六仪的第几宫位
        for (int i = 0; i < 9; i++) {
            if (timeGan.equals(sanQiLiuYi[i])) {
                setNewZhiFuGongWeiNumber(i + 1);
                break;
            }
        }

    }

//-----------------------------------------------------------------

    /**
     * 设置【九星】落入地盘中的'三奇六仪'信息 <旋转前>【顺时针旋转】
     */
    public void jiuXingSanQiLiuYi() {

        String[] sanQiLiuYi = getSanQiLiuYi(); // 获取三奇六仪(1~9宫)
        int zhiFuGongWeiShu = getZhiFuGongWeiNumber();// 获取[值符]旋转前宫位数
        if(zhiFuGongWeiShu == 5){
            zhiFuGongWeiShu = 2;
        }

        String[] info = new String[9]; // 存放'三奇六仪'信息

        List<Integer> integers = sjqmOther.SHUN_GONG.get(zhiFuGongWeiShu);
        for (int i = 0; i < integers.size(); i++) {
            info[i] = sanQiLiuYi[integers.get(i) - 1];
        }

        // 中五宫元素添加至信息末尾
        info[8] = sanQiLiuYi[4];

        // 设置数据
        setJiuXingSanQiLiuYi(info);

    }

    /**
     * 设置【九星】落入地盘信息 <旋转后>
     *
     * @param isFlag true：有宫位标识     false：无宫位标识
     */
    private void newJiuXing(boolean isFlag) {

        String[] jiuXing = sjqmOther.getJiuXing(); // 获取九星信息（'天禽星'除外）
        String zhiFu = getZhiFu(); // 获取值符
        int newZhiFuGongWeiShu = getNewZhiFuGongWeiNumber();// 获取[值符]旋转后宫位数

        String[] info = new String[10]; // 记录九星信息
        int index = 0; // 记录[值符]在九星里的索引数

        // 遇五宫则寄二宫
        if(newZhiFuGongWeiShu == 5){
            newZhiFuGongWeiShu = 2;
        }

        // 获取[值符]在九星里的索引数
        for (int i = 0; i < jiuXing.length; i++) {
            if (zhiFu.equals(jiuXing[i])) {
                index = i;
                break;
            }
        }

        // 判断索引值是否越界
        if (index > 7) {
            index = 0;
        }

        // 遍历
        List<Integer> integers = sjqmOther.SHUN_GONG.get(newZhiFuGongWeiShu);
        for (Integer integer : integers) {
            // 判断索引值是否越界
            if (index > 7) {
                index = 0;
            }
            info[integer] = jiuXing[index];
            if ("天芮星".equals(info[integer])) {
                info[integer] = jiuXing[index] + "、天禽星";
            }
            index++;
        }

        // 去除空元素
        info = Utils.deleteEmptyElement(info);
        // 向中五宫添加""元素
        info = Utils.insert(info, 4, "");

        // 判断是否带宫位标识
        if(isFlag){
            for (int i = 0; i < info.length; i++) {
                String han = Utils.shuToHan(i + 1); // 数字转汉字
                info[i] = (han + "宫：【" + info[i] + "】");
            }
        }

        //设置信息
        setNewJiuXing(info);
        setTianPan(info);

    }

//....................................................

    /**
     * $根据[值符]判断[值使]（方法一）
     * <p>
     * ★方法说明：[值符]为'天禽星'时，一律用<死门>做为[值使]
     */
    private void zhiShi1() {
        setZhiShi("死门");
    }

    /**
     * $根据[值符]判断[值使]（方法二）
     * <p>
     * ★方法说明：
     * [值符]为'天禽星'时，阳遁用<生门>做为[值使]
     * [值符]为'天禽星'时，阴遁用<死门>做为[值使]
     */
    private void zhiShi2() {

        if ("阳遁".equals(getYinYangDun())) {
            setZhiShi("生门");
        } else setZhiShi("死门");

    }

    /**
     * $根据[值符]判断[值使]（方法三）
     * <p>
     * ★方法说明：
     * 天禽星为值符时，（冬至、小寒、大寒）三个节气，用《休门》为值使；
     * 天禽星为值符时，（立春，雨水，惊蛰）三个节气，用《生门》为值使；
     * 天禽星为值符时，（春分、清明、谷雨）三个节气，用《伤门》为值使。
     * 天禽星为值符时，（立夏、小满、芒种）三个节气，用《杜门》为值使；
     * 天禽星为值符时，（夏至、小暑、大暑）三个节气，用《景门》为值使；
     * 天禽星为值符时，（立秋、处暑、白露）三个节气，用《死门》为值使；
     * 天禽星为值符时，（秋分、寒露、霜降）三个节气，用《惊门》为值使；
     * 天禽星为值符时，（立冬、小雪、大雪）三个节气，用《开门》为值使。
     */
    private void zhiShi3() {

        A:
        for (int i = 1; i <= 8; i++) {
            for (int j = 0; j < 3; j++) {
                String jieQi = sjqmOther.BA_MEN_JIE_QI.get(i).get(j);
                if (jieQi.equals(getJieQi())) {
                    switch (i) {
                        case 1:
                            setZhiShi("休门");
                            break A;
                        case 2:
                            setZhiShi("生门");
                            break A;
                        case 3:
                            setZhiShi("伤门");
                            break A;
                        case 4:
                            setZhiShi("杜门");
                            break A;
                        case 5:
                            setZhiShi("景门");
                            break A;
                        case 6:
                            setZhiShi("死门");
                            break A;
                        case 7:
                            setZhiShi("惊门");
                            break A;
                        case 8:
                            setZhiShi("开门");
                            break A;
                    }
                }
            }
        }

    }

//....................................................

    /**
     * 获取并设置[值使]旋转后落入的宫位
     */
    private void newZhiShiGongWei() {

        String xunZhi = String.valueOf(getXunShou().toCharArray()[1]); // 获取[旬首]中的'地支'（代表当前[值使]所处的时间）
        String timeZhi = lunarDate.getTimeZhi(); // 获取时支
        int zhiShiShu = getZhiShiGongWeiNumber(); // 获取[值使]旋转前所处的宫位数

        int sum = 0; // 记录【[旬首]中的'地支'】和【时支】相同时一共比较了几次
        int xunZhiNumber = 0; // 记录[旬首]中的'地支'在十二地支中的数字
        // 1、获取[旬首]中的'地支'数字
        for (int i = 0; i < 12; i++) {
            if (xunZhi.equals(sjqmOther.getDiZhi()[i])) {
                xunZhiNumber = i;
                break;
            }
        }

        // 2、获取【[旬首]中的'地支'】和【时支】相同时一共比较的次数
        for (int i = 0; i <= 12; i++) {
            // 从 xunZhiNumber个 开始向后查找
            if ("亥".equals(sjqmOther.getDiZhi()[xunZhiNumber])) {
                xunZhiNumber = 0; // 重新从第一个元素开始查找
                sum++; // 查询次数+1
            }
            if (!timeZhi.equals(sjqmOther.getDiZhi()[xunZhiNumber])) {
                xunZhiNumber++; // 继续查找下一个元素
                sum++; // 查询次数+1
            }
            if (timeZhi.equals(sjqmOther.getDiZhi()[xunZhiNumber])) {
                break; // 元素相同，则停止查找
            }
        }

        // 3、用【[值使]旋转前所处的宫数】+【一共查找的次数】，获取[值使]旋转后所处的宫位
        for (int i = 1; i <= sum; i++) {
            zhiShiShu++;
            // 判断阴阳遁
            if ("阳遁".equals(getYinYangDun())) {
                if (zhiShiShu > 9) {
                    zhiShiShu = 1;
                }
            } else {
                if (zhiShiShu >= 9) {
                    zhiShiShu = 1;
                }
            }

        }

        // 4、判断[值使]旋转后所处的宫位
        if (zhiShiShu == 5) {
            zhiShiShu = 2; // 五宫寄二宫
        }

        // 5、设置信息
        setNewZhiShiGongWeiNumber(zhiShiShu);


    }

    /**
     * ★获取并设置【人盘】
     *
     * @param baMen  八门数据
     * @param isFlag true：有宫位标识     false：无宫位标识
     */
    private void ren(Map<Integer, List<Integer>> baMen, boolean isFlag) {

        String zhiShi = getZhiShi(); // 获取[值使]
        int newZhiShiGongWeiShu = getNewZhiShiGongWeiNumber(); // 获取[值使]旋转后落入的宫位
        if(newZhiShiGongWeiShu == 5){
            newZhiShiGongWeiShu = 2;
        }
        String[] bm = sjqmOther.getBaMen(); // 获取八门

        int index = 0; // 记录[值使]在八门中的索引值
        String[] renPan = new String[10]; // 记录【人盘】

        // 1、获取[值使]在八门中的索引值
        for (int i = 0; i < bm.length; i++) {
            if (bm[i].equals(zhiShi)) {
                index = i;
                break;
            }
        }

        // 2、判断索引值是否越界
        if (index > 7) {
            index = 0;
        }

        // 3、根据【[值使]旋转后落入的宫位】获取【（顺\逆）时针宫树旋转顺序】
        List<Integer> xu = baMen.get(newZhiShiGongWeiShu);
        for (Integer integer : xu) {
            if (index > 7) {
                index = 0;
            }
            renPan[integer] = sjqmOther.getBaMen()[index];
            index++;
        }

        // 4、删除空元素，并向4索引处插入""元素
        String[] newRenPan = Utils.insert(Utils.deleteEmptyElement(renPan), 4, "");

        // 5、判断是否带宫位标识
        if (isFlag) {
            //带宫位标识
            for (int i = 0; i < newRenPan.length; i++) {
                String han = Utils.shuToHan(i + 1); // 数字转汉字
                newRenPan[i] = (han + "宫：【" + newRenPan[i] + "】");
            }
        }

        // 6、设置数据
        setRenPan(newRenPan);


    }

//----------------------------------------------------------------------------------------------------------------------

    /**
     * 【正授】判断：{上元符头(甲子、甲午、己卯、己酉)}碰到{节气这一天的日干支}
     */
    public void zhengShou() {

        // 获取此日的日干支（日柱）
        String ganZhi = lunarDate.getDayInGanZhi();

        // 判断日干支是否为其中一种，并且此日又为节气（0：正授   1：非正授）
        boolean isFlag = ganZhi.equals("甲子") || ganZhi.equals("甲午") || ganZhi.equals("己卯") || ganZhi.equals("己酉");
        if (isFlag && !"".equals(lunarDate.getJieQi())) {
            setZhengShou(0);
        } else setZhengShou(1);

    }

    /**
     * 【超神】判断：{上元符头(甲子、甲午、己卯、己酉)}在{节气}前面
     */
    public void chaoShen() {

        String jieQi = lunarDate.getJieQi(); // 获取节气
        String ganZhi = lunarDate.getDayInGanZhi(); // 获取日干支

        // 1、十二符头判断
        if (isFlagFuTou(ganZhi)) {
            // 日干支包含十二符头
            setChaoShen(1); // 非超神
            return;
        }

        // ★2、此日是节气
        if (!jieQi.equals("")) {
            // ①判断[节气]前面是否有[上元符头]【最多9天之内，若大于9天则需要'置润'】
            for (int i = 1; i < 10; i++) {
                // Ⅰ向前数第i天的日干支（日柱）
                String dayGanZhi = lunarDate.next(-i).getDayInGanZhi();
                // Ⅱ判断上元符头
                if (isFlagUpFuTou(dayGanZhi)) {
                    setChaoShen(0); // 超神
                    return;
                }
            }
        }

        // ★3、此日不是节气
        if (jieQi.equals("")) {
            // --->判断此日的日干支是否为十二符头
            if (isFlagFuTou(ganZhi)) {
                setChaoShen(1); // 非超神
            } else {
                // ☆①此日在节气【之前】，并且在节气前的4天之内
                for (int i = 1; i < 5; i++) {
                    String dayGanZhi = lunarDate.next(-i).getDayInGanZhi(); // 获取向前数第i天的日干支（日柱）
                    for (String ft : sjqmOther.getUpFuTou()) {
                        if (dayGanZhi.equals(ft)) {
                            setChaoShen(0); // 超神
                            return;
                        }
                    }
                }
                // ☆②此日在节气【之后】
                for (int i = 1; i < 5; i++) {
                    String dayGanZhi = lunarDate.next(-i).getDayInGanZhi(); // 获取向前数第i天的日干支（日柱）
                    String jq = lunarDate.next(-i).getJieQi(); // 获取向前数第i天的节气
                    // Ⅰ判断是否为：除了上元符头的其他符头
                    if (isFlagBaFuTou(dayGanZhi)) {
                        setChaoShen(1); // 非超神
                        return;
                    }
                    // Ⅱ 判断是否碰到节气
                    if (jq.equals("")) {
                        // (1)无节气，但出现上元符头
                        if (isFlagUpFuTou(dayGanZhi)) {
                            setChaoShen(1); // 非超神
                            return;
                        }
                    } else {
                        // (2)有节气，再向前数天数
                        setChaoShen(0); // 超神
                        return;
                    }
                }
            }
        }

    }

    /**
     * 【接气】判断：{上元符头(甲子、甲午、己卯、己酉)}在{节气}后面（一般在'置润'后出现）
     */
    public String jieQi(Lunar lunarDate) {

        // TODO：【接气】-待编写

        return null;

    }

    /**
     * ★置润派：置润法（只有在[芒种]和[大雪]两个节气时才能'置润'，否则结果可能为null）
     *
     * @return 冬至上元第一天的日干支
     */
    @Deprecated
    public String zhiRun() {

        String dayGanZhi = null;
        // 获取该节气的上元符头：甲子
        for (int i = 0; i < 15; i++) {
            String ganZhi = lunarDate.next(-i).getDayInGanZhi(); // 第前i天的日干支
            if (ganZhi.equals("甲子")) {
                // 向后数第15天的日干支
                dayGanZhi = lunarDate.next(15 - i).getDayInGanZhi(); // 这一天作为下一个节气（冬至或夏至）的上元
                break;
            }
        }
        return dayGanZhi;

    }

    /**
     * ★无润派：拆补法
     */
    private void chaiBu() {

        // TODO：【★无润派：拆补法】-待编写

    }

//======================================================================================================================

    /**
     * 获取并设置【节气】
     */
    public void jieQi() {

        String jieQi = lunarDate.getJieQi(); // 节气

        // 1、判断此日是否为节气
        if (jieQi.equals("")) {
            // 更新节气
            A:
            for (int i = 0; i < 15; i++) {
                String jq = lunarDate.next(-i).getJieQi(); // 向前数第i天的节气
                String ganZhi = lunarDate.next(-i).getDayInGanZhi(); // 向前数第i天的日干支
                // 判断日干支是否碰到'甲子'，并且没有碰到上一个节气（【芒种、大雪】除外）
                if (ganZhi.equals("甲子")) {
                    // 碰到'甲子'，则转为向后数天数（目的：遇到[芒种]、[大雪]两个节气要'置闰'）
                    int j = 1;
                    for (; ; ) {
                        jq = lunarDate.next(j).getJieQi();
                        j++;
                        // 遇到节气则停止
                        if (!jq.equals("")) {
                            jieQi = jq;
                            break A;
                        }
                    }
                } else {
                    // 未碰到'甲子'，则继续向前数天数，直到遇到节气才停止
                    if (!jq.equals("")) {
                        jieQi = jq;
                        break;
                    }
                }
            }
        }
        setJieQi(jieQi);

    }

    /**
     * 获取并设置[阴遁]或[阳遁]
     */
    public void yinYangDun() {

        /*
            阴遁：（夏至、小暑、大暑、立秋、处暑、白露、秋分、寒露、霜降、立冬、小雪、大雪）
            阳遁：（冬至、小寒、大寒、立春、雨水、惊蛰、春分、清明、谷雨、立夏、小满、芒种）
         */
        //(夏至-大雪)：阴遁
        String dun = "阴遁";
        //(冬至-芒种)：阳遁
        for (int i = 0; i <= 11; i++) {
            if (sjqmOther.solaTerms[i].equals(getJieQi())) {
                dun = "阳遁";
                break;
            }
        }
        setYinYangDun(dun);

    }

    /**
     * 获取并设置（上\中\下）元
     */
    public void sanYuan() {

        String dayG = lunarDate.getDayGan(); // 获取日天干
        String dayGz = lunarDate.getDayInGanZhi(); // 获取日干支

        int yuan = 0; // ★记录状态
        // ★情况一：若该日干支为[甲子、甲午、己卯、己酉]，则为上元
        if ("甲子".equals(dayGz) || "甲午".equals(dayGz) || "己卯".equals(dayGz) || "己酉".equals(dayGz)) {
            yuan = 1;
            // 若该日干支为[甲申、甲寅、己巳、己亥]，则为中元
        } else if ("甲申".equals(dayGz) || "甲寅".equals(dayGz) || "己巳".equals(dayGz) || "己亥".equals(dayGz)) {
            yuan = 2;
            // 若该日干支为[甲戌、甲辰、己丑、己未]，则为下元
        } else if ("甲戌".equals(dayGz) || "甲辰".equals(dayGz) || "己丑".equals(dayGz) || "己未".equals(dayGz)) {
            yuan = 3;
        }

        // ★情况二：日天干为【乙\丙\丁\戊】
        if ("乙".equals(dayG) || "丙".equals(dayG) || "丁".equals(dayG) || "戊".equals(dayG)) {
            // 向前数天数并判断日地支
            A:
            for (int i = 1; i < 10; i++) {
                // 获取前i天的 日干支
                String dayGz1 = lunarDate.next(-i).getDayInGanZhi();

                //判断 日干支
                switch (dayGz1) {
                    case "甲子":
                    case "甲午":
                        yuan = 1; // 上元
                        break A;
                    case "甲寅":
                    case "甲申":
                        yuan = 2; // 中元
                        break A;
                    case "甲辰":
                    case "甲戌":
                        yuan = 3; // 下元
                        break A;
                }
            }
        }

        // ★情况三：日天干为【庚\辛\壬\癸】
        if ("庚".equals(dayG) || "辛".equals(dayG) || "壬".equals(dayG) || "癸".equals(dayG)) {
            // 向前数天数并判断日干支
            B:
            for (int i = 1; i < 5; i++) {
                // 获取前i天的 日干支
                String dayGz1 = lunarDate.next(-i).getDayInGanZhi();

                //判断 日干支
                switch (dayGz1) {
                    case "己卯":
                    case "己酉":
                        yuan = 1; // 上元
                        break B;
                    case "己巳":
                    case "己亥":
                        yuan = 2; // 中元
                        break B;
                    case "己丑":
                    case "己未":
                        yuan = 3; // 下元
                        break B;
                }
            }
        }

        // 设置信息
        setSanYuan(yuan);

    }

    /**
     * 二次判断【上中下元】正确性：根据符头再次判断
     */
    public void isFlagSanYuan() {

        int yuan = 0; // ★记录状态

        switch (getFuTou()) {
            case "甲子":
            case "甲午":
            case "己卯":
            case "己酉":
                yuan = 1; // 上元
                break;
            case "甲寅":
            case "甲神":
            case "己巳":
            case "己亥":
                yuan = 2; // 中元
                break;
            case "甲辰":
            case "甲戌":
            case "己丑":
            case "己未":
                yuan = 3; // 下元
        }
        // 二次判断
        if (yuan == getSanYuan()) {
            setSanYuan(yuan);
        } else {
            System.out.println("/n**********（上/中/下）元二次判断时出现问题！**********\n");
        }

    }

    /**
     * 获取并设置【局数】
     */
    public void juNumber() {

        // 记录局数
        int juNumber = 0;

        // 遍历二十四节气
        A:
        for (String solaTerm : sjqmOther.solaTerms) {
            // 判断节气
            if (solaTerm.equals(getJieQi())) {
                //判断(上、中、下)元
                switch (getSanYuan()) {
                    case 1: // 上元
                        juNumber = sjqmOther.SOLATERMS_SHU.get(getJieQi()).get(0);
                        break A;
                    case 2: // 中元
                        juNumber = sjqmOther.SOLATERMS_SHU.get(getJieQi()).get(1);
                        break A;
                    case 3: // 下元
                        juNumber = sjqmOther.SOLATERMS_SHU.get(getJieQi()).get(2);
                        break A;
                }
            }
        }
        setJuNumber(juNumber);

    }

    /**
     * 获取并设置【符头】
     */
    public void fuTou() {

        String fuTou = null; // 符头

        // 判断是否为'正授'
        if (getZhengShou() == 0) {
            setFuTou(lunarDate.getDayInGanZhi());
        } else {
            // 2、通过日干支向前数，判断符头
            // ①外层循环：向前数天数
            A:
            for (int i = 0; i < 5; i++) {
                // 向前数第i天的日干支（日柱）
                String dayGanZhi = lunarDate.next(-i).getDayInGanZhi();
                // ②内层循环：判断十二符头
                for (int j = 0; j < 12; j++) {
                    if (dayGanZhi.equals(sjqmOther.getFuTou()[j])) {
                        fuTou = sjqmOther.getFuTou()[j];
                        break A;
                    }
                }
            }
        }
        // 设置符头
        setFuTou(fuTou);

    }

//----------------------------------------------------------------------------------------------------------------------

    /**
     * 获取并设置【三奇六仪】
     */
    public void sanQiLiuYi() {
        setSanQiLiuYi(getDiPan(sjqmOther.YANG_DUN, sjqmOther.YIN_DUN));
    }

    /**
     * 获取并设置【六甲隐位】
     */
    public void liuJiaYinWei() {
        setLiuJiaYinWei(getDiPan(sjqmOther.YANG_DUN_WEI, sjqmOther.YIN_DUN_WEI));
    }

    /**
     * ★获取并设置【地盘】（三奇六仪+六甲隐位）
     *
     * @param isFlag true：有宫位标识     false：无宫位标识
     */
    public void diPan(boolean isFlag) {

        String[] sanQi = getSanQiLiuYi(); // 获取三奇六仪
        String[] liuJia = getLiuJiaYinWei(); // 获取六甲隐位
        String[] diPan = new String[9]; // 用于存放合并后的地盘信息

        // 遍历'三奇六仪'
        for (int i = 0; i < sanQi.length; i++) {
            // 遍历'六甲隐位'
            for (int j = 0; j < liuJia.length; j++) {
                String han = Utils.shuToHan(i + 1); // 数字转汉字
                // 是否带宫位标识
                if (isFlag) {
                    if ("".equals(liuJia[j])) {
                        diPan[j] = han + "宫:【" + sanQi[i] + "】";
                    } else diPan[j] = (han + "宫:【" + sanQi[i] + "(" + liuJia[j] + ")】");
                } else {
                    if ("".equals(liuJia[j])) {
                        diPan[j] = sanQi[i];
                    } else diPan[j] = (sanQi[i] + "(" + liuJia[j] + ")");
                }
                i++;
            }
        }
        // 设置信息
        setDiPan(diPan);

    }

//----------------------------------------------------------------------------------------------------------------------

    /**
     * 获取并设置【旬首】
     */
    public void xunShou() {

        int ganShu = sjqmOther.TIAN_GAN.get(lunarDate.getTimeGan()); // 根据 时天干 获取对应数字
        int zhiShu = sjqmOther.DI_ZHI.get(lunarDate.getTimeZhi()); // 根据 时地支 获取对应数字

        // 若(地支数-天干数)<0，则(地支数+12)
        if ((zhiShu - ganShu) < 0) {
            zhiShu += 12;
        }

        // 记录旬首
        String xunShou = null;
        for (int i = 0; i <= 10; i += 2) {
            if ((zhiShu - ganShu) == i) {
                xunShou = sjqmOther.LIU_JIA.get(i);
                break;
            }
        }

        // 设置信息
        setXunShou(xunShou);


    }

    /**
     * 获取并设【值符】与【值使】 &&调取frontGongWei()方法
     */
    public void fuShi(int number) {

        int gongShu = zhiFuGongWei(); // 【值符(九星之一)】落入地盘的宫位 <旋转前>

        String[] fuShi = new String[2]; // 记录[值符]与[值使]
        String zhiFu = sjqmOther.JIU_XING.get(gongShu); // 根据宫数获取对应的 [值符（九星之一）]
        String zhiShi = sjqmOther.BA_MEN.get(gongShu); // 根据宫数获取对应的 [值使（八门之一）]

        //添加数据
        fuShi[0] = zhiFu; // 值符
        fuShi[1] = zhiShi; // 值使

        // 设置信息
        setZhiFu(fuShi[0]); // 值符
        setZhiShi(fuShi[1]); // 值使

        // 当[值符]为'天禽星'时再次判断
        if ("天禽星".equals(getZhiFu())) {
            if (number == 1) zhiShi1(); // 方法一
            if (number == 2) zhiShi2(); // 方法二
            if (number == 3) zhiShi3(); // 方法三
        }

    }

//----------------------------------------------------------------------------------------------------------------------

    /**
     * 获取并设置【值符(九星之一)】落入地盘的宫位 <旋转后> &&调取afterGongWei()方法
     */
    public void newGongWei() {
        newZhiFuGongWei();
    }

    /**
     * ★获取并设置【天盘】
     *
     * @param isFlag true：有宫位标识     false：无宫位标识
     */
    public void tianPan(boolean isFlag) {
        newJiuXing(isFlag);
    }

//----------------------------------------------------------------------------------------------------------------------

    /**
     * ★获取并设置【人盘】
     *
     * @param isFlag true：有宫位标识     false：无宫位标识
     * @param shunXu true：阳遁顺排，阴遁逆排     false：一律顺排
     */
    public void renPan(boolean isFlag, boolean shunXu) {

        newZhiShiGongWei(); // 获取并设置[值使]旋转后落入的宫位

        if (shunXu) {
            // 判断阴阳遁
            if ("阳遁".equals(getYinYangDun())) {
                // ①阳遁顺排
                ren(sjqmOther.SHUN_GONG, isFlag);
            } else {
                // ②阴遁逆排
                ren(sjqmOther.NI_GONG, isFlag);
            }
        } else {
            // 一律顺排
            ren(sjqmOther.SHUN_GONG, isFlag);
        }

    }

//----------------------------------------------------------------------------------------------------------------------

    /**
     * ★获取并设置【神盘】
     *
     * @param isFlag true：有宫位标识     false：无宫位标识
     */
    public void shenPan(boolean isFlag) {

        // 当[值符]落入五宫内时，则寄二宫
        if (getNewZhiFuGongWeiNumber() == 5) {
            setNewZhiFuGongWeiNumber(2);
        }

        String[] shenPan; // 神盘信息
        // 判断阴阳遁
        if ("阳遁".equals(getYinYangDun())) {
            // ①阳遁顺排
            shenPan = sjqmOther.BA_SHEN_SHUN.get(getNewZhiFuGongWeiNumber()).toArray(new String[]{});
        } else {
            // ②阴遁逆排
            shenPan = sjqmOther.BA_SHEN_NI.get(getNewZhiFuGongWeiNumber()).toArray(new String[]{});

        }

        // 判断是否带宫位标识
        if (isFlag) {
            //带宫位标识
            for (int i = 0; i < shenPan.length; i++) {
                String han = Utils.shuToHan(i + 1); // 数字转汉字
                shenPan[i] = (han + "宫：【" + shenPan[i] + "】");
            }
        }

        // 设置信息
        setShenPan(shenPan);

    }

}
